local table_concat = table.concat
local table_insert = table.insert
local Mqp = require 'script.mpq.mpq'

local MDX = {}

local mt = {}
setmetatable( MDX, MDX )
MDX.__index = mt


MDX.REPLACEABLEID = 'ReplaceableID'

function MDX.init(data)
	MDX.output_path = fs.path( data.output_path )
	MDX.input_path = fs.path( data.input_path )
	MDX.input_path_s = data.input_path
	MDX.dir = data.dir

	if Mqp.is_lni_map then
		MDX.custom_file_path = MDX.input_path / 'resource'
	else
		MDX.custom_file_path = MDX.input_path
	end
end

---是否是自定义图片
function MDX.is_custom( blp_path )
	if blp_path ~= MDX.REPLACEABLEID then
		if fs.exists( MDX.custom_file_path/blp_path ) then
			return true
		else
			return Mqp.is_custom( blp_path )
		end
	else
		return false
	end
end

---用 0 填充字符串至256长度
local _fill_path_list = {}
local get_fill_string = function ( len )
	if not _fill_path_list[len] then
		local s = {}
		for i = 1, len do
			table_insert(s, string.char(0))
		end
		_fill_path_list[len] = table_concat(s, '')
	end
	return _fill_path_list[len]
end

--实际上只是用来补全，贴图路径的
function MDX.fill_blp_path(str, max_len )
	local len = #str
	local fill_str = get_fill_string( (max_len or 256) -len )
	return str .. fill_str
end

function MDX.new( path )
	local file = io.open(path, 'rb')
	local o = setmetatable({}, MDX)
	if file then
		local self = o
		self.path = path
		self.strings = file:read('*a')
		file:close()
	else
		log.error(('创建mdx时，不存在路径文件(%s)'):format(path))
	end

	o:get_blp_paths()

	return o
end

--偏移
MDX.cell_offsizes = {
	4,--贴图的材质参数等
	256,--路径	REPLACEABLEID
	4,--总是为0
	4,--贴图的材质参数等
}

--第一个贴图，相对特征(TEXS)后的字节偏移
MDX.offsize_of_first_blp = 4
MDX.offsize_of_blp_count = 1

function mt:get_blp_paths()
	--特征开始点
	local _, start = self.strings:find('TEXS')
	
	local blps = {}
	if start then
		start = start+1

		--一个跟blp数量相关的特征，相对特征name后第一位
		--值=数量*12
		local offsize_of_len = 0
		local count_len = self.strings:sub(start+offsize_of_len, start+offsize_of_len):byte()

		--blp数量，相对特征name后第一位
		local offsize_of_blp_count = MDX.offsize_of_blp_count
		local count = self.strings:sub(start+offsize_of_blp_count, start+offsize_of_blp_count):byte()

		
		--长度
		local cell_offsizes = MDX.cell_offsizes
		local cell_len = cell_offsizes[1] + cell_offsizes[2] + cell_offsizes[3] + cell_offsizes[4]
		local cell_head = cell_offsizes[1]
		local cell_body = cell_offsizes[2]
		local cell_foot = cell_offsizes[3]
		local cell_tail = cell_offsizes[4]

		--第一个blp的偏移，相对特征name后第一位
		local first_blp_position = start + MDX.offsize_of_first_blp

		for number = 1, count do
			local position_first = first_blp_position + cell_len*(number-1)
			local blp = {}
			local head = 0
			for i = 1, #MDX.cell_offsizes do
				local len = MDX.cell_offsizes[i]
				local centent = self.strings:sub(position_first+head, position_first+head+len-1)
				blp[i] = centent
				if i == 2 then
					blp[i] = blp[i]:gsub('%z', '')
					if blp[i] == '' then
						blp[i] = MDX.REPLACEABLEID
					end
				end
				head = head + len
			end
			
			table_insert(blps, blp)
		end
	end

	self.blp_contents = blps
	self.blps = {}
	for _, blp in ipairs(blps) do
		table_insert(self.blps, blp[2])
	end

	return self.blps
end

function mt:is_init_blps()
	return self.blp_contents and true
end

function mt:get_output_path()
	return self.output_path or tostring(MDX.output_path)
end


---@param out_path string 输出路径，不应该带有.mdx后缀
function mt:change_blp_paths( out_path )

	local informations = {}
	--缺少的贴图
	informations.deficient = {}
	--系统自带的贴图
	informations.system_own = {}
	--原来的路径
	informations.last_path = self.path
	--外导的
	informations.custom = {}


	local _, start = self.strings:find('TEXS')
	local out_content

	local wait_to_copy = {}

	if start then

		if not self:is_init_blps() then
			self:get_blp_paths()
		end

		start = start + 1

		--blp数量，相对特征name后第一位
		local offsize_of_blp_count = MDX.offsize_of_blp_count
		local count = self.strings:sub(start+offsize_of_blp_count, start+offsize_of_blp_count):byte()
		
		--第一个blp的偏移，相对特征name后第一位
		local offsize_of_first_blp = MDX.offsize_of_first_blp
		local first_blp_position = start+offsize_of_first_blp

		--获取第一个blp的第一个字符的前面所有的文本
		local new_file_string = {}
		table_insert(new_file_string, self.strings:sub(1, first_blp_position-1))
		
		local index = 1
		for number = 1, #self.blps do
			local blp = self.blps[number]
			if MDX.is_custom(blp) then
				--外导的blp
				local type = Utility.Get_filetype(blp) or 'blp'
				blp = ('_%d.%s'):format( index, type)
				index = index + 1
				wait_to_copy[MDX.custom_file_path / self.blps[number]] = blp
				table_insert( informations.custom, {
					old = self.blps[number],
					new = blp,
				})
			else
				--自带的文件
				if self.blps[number] == MDX.REPLACEABLEID then
					--不知道这样处理 REPLACEABLEID 行不行
					blp = ''
					table_insert( informations.system_own, MDX.REPLACEABLEID )
				else
					blp = self.blps[number]
					table_insert( informations.system_own, blp )
				end
			end
			blp = MDX.fill_blp_path( blp )

			table_insert(new_file_string, self.blp_contents[number][1])
			table_insert(new_file_string, blp)
			table_insert(new_file_string, self.blp_contents[number][3])
			table_insert(new_file_string, self.blp_contents[number][4])
		end


		--获取最后一个blp后面所有的文本
		table_insert(new_file_string, self.strings:sub( first_blp_position+count*(268) ))
		out_content = table_concat(new_file_string)
	else
		out_content = self.strings
	end

	local output_path_name
	for old, new in pairs(wait_to_copy) do
		if not fs.exists( old ) then
			table_insert( informations.deficient, tostring(old) )
		end
	end

	if #informations.deficient == 0 then
		output_path_name = ('%s\\%s'):format(self:get_output_path(), out_path)
	else
		output_path_name = ('%s\\%s(lack-%.d)'):format(self:get_output_path(), out_path, #informations.deficient)
	end

	fs.create_directory( fs.path( output_path_name ) )
	for old, new in pairs(wait_to_copy) do
		if fs.exists( old ) then
			fs.copy_file( old, fs.path( MDX.output_path / out_path / new), true )
		end
	end

	local name = ('%s\\%s.mdx'):format( output_path_name, out_path )
	local file = io.open( name, 'wb' )
	file:write( out_content )
	file:close()

	self:write_change_infomation( output_path_name, informations )

end


---搬运过去，保持路径，保留原来的名称
---@param out_path string 输出路径，不应该带有.mdx后缀
function mt:collect_blp_paths( out_path )

	local informations = {}
	--缺少的贴图
	informations.deficient = {}
	--系统自带的贴图
	informations.system_own = {}
	--原来的路径
	informations.last_path = self.path
	--外导的
	informations.custom = {}


	local _, start = self.strings:find('TEXS')
	local out_content
	out_content = self.strings

	local wait_to_copy = {}

	if start then

		if not self:is_init_blps() then
			self:get_blp_paths()
		end

		start = start + 1

		--blp数量，相对特征name后第一位
		local offsize_of_blp_count = MDX.offsize_of_blp_count
		local count = self.strings:sub(start+offsize_of_blp_count, start+offsize_of_blp_count):byte()
		
		--第一个blp的偏移，相对特征name后第一位
		local offsize_of_first_blp = MDX.offsize_of_first_blp
		local first_blp_position = start+offsize_of_first_blp

		--获取第一个blp的第一个字符的前面所有的文本
		local new_file_string = {}
		table_insert(new_file_string, self.strings:sub(1, first_blp_position-1))
		
		
		for number = 1, #self.blps do
			local blp = self.blps[number]
			if MDX.is_custom(blp) then
				--外导的blp
				-- blp = Utility.get_file_name( blp )
				wait_to_copy[MDX.custom_file_path / self.blps[number]] = blp
				table_insert( informations.custom, {
					old = self.blps[number],
					new = blp,
				})
			else
				--自带的文件
				if self.blps[number] == MDX.REPLACEABLEID then
					--不知道这样处理 REPLACEABLEID 行不行
					blp = ''
					table_insert( informations.system_own, MDX.REPLACEABLEID )
				else
					blp = self.blps[number]
					table_insert( informations.system_own, blp )
				end
			end
			blp = MDX.fill_blp_path( blp )

			table_insert(new_file_string, self.blp_contents[number][1])
			table_insert(new_file_string, blp)
			table_insert(new_file_string, self.blp_contents[number][3])
			table_insert(new_file_string, self.blp_contents[number][4])
		end

	end

	local output_path_name
	for old, new in pairs(wait_to_copy) do
		if not fs.exists( old ) then
			table_insert( informations.deficient, tostring(old) )
		end
	end

	if #informations.deficient == 0 then
		output_path_name = ('%s\\%s'):format(self:get_output_path(), out_path)
	else
		output_path_name = ('%s\\%s(lack-%.d)'):format(self:get_output_path(), out_path, #informations.deficient)
	end
	
	fs.create_directory( fs.path( output_path_name ) )
	for old, new in pairs(wait_to_copy) do
		if fs.exists( old ) then
			local paths = string.split( new, '\\' )
			local file_name = Utility.get_file_name(new)
			local path = MDX.output_path / out_path
			if #paths > 1 then
				for i = 1, #paths-1 do
					path = path / paths[i]
					fs.create_directory( path )
				end
			end
			fs.copy_file( old, fs.path( path / file_name), true )
		end
	end
	
	local name = ('%s\\%s.mdx'):format( output_path_name, out_path )
	local file = io.open( name, 'wb' )
	file:write( out_content )
	file:close()

	self:write_change_infomation( output_path_name, informations )

end

local function get_col_content_by_table( tab )
	if not tab or #tab == 0 then
		return '\t'	..	'无'
	end
	local ss = {}
	for _, line in ipairs(tab) do
		table_insert(ss, '\t-' .. line)
	end
	return table_concat(ss, '\n')
end

---写出额外信息
function mt:write_change_infomation( out_path, informations )
	local extra_information = ('%s\\infomation.txt'):format( out_path )

	local file = io.open( extra_information, 'wb' )
	local centent = {}
	table_insert(centent, '原路径：'.. informations.last_path)
	table_insert(centent, '缺少的贴图：')
	table_insert(centent, get_col_content_by_table(informations.deficient))
	table_insert(centent, '系统自带的贴图：')
	table_insert(centent, get_col_content_by_table(informations.system_own))
	table_insert(centent, '外导贴图')
	local tmp = {}
	for _, paths in ipairs(informations.custom) do
		table_insert(tmp, ('%s -> %s'):format(paths.old, paths.new))
	end
	table_insert(centent, get_col_content_by_table( tmp ))
	table_insert(centent, '')
	file:write( table_concat(centent, '\n') )
	file:close()

end


return MDX